package com.jgame.secondarymarket.domain.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jgame.secondarymarket.domain.product.entity.Product;
import com.jgame.secondarymarket.domain.product.entity.ProductProperties;
import com.jgame.secondarymarket.domain.product.entity.Specification;
import com.jgame.secondarymarket.domain.product.repository.ProductPropertiesRepository;
import com.jgame.secondarymarket.domain.product.repository.ProductRepository;
import com.jgame.secondarymarket.domain.product.repository.SpecificationRepository;
import com.jgame.secondarymarket.domain.product.service.SpecificationService;
import com.jgame.secondarymarket.infrastructure.excetpions.BussnessException;
import com.jgame.secondarymarket.interfaces.assembler.product.SpecificationAssembler;
import com.jgame.secondarymarket.interfaces.query.page.product.PageSpecificationQuery;
import com.jgame.secondarymarket.interfaces.vo.product.ProductPropertiesVO;
import com.jgame.secondarymarket.interfaces.vo.product.SpecificationVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @title: SpecificationImpl
 * @Author Wangsj
 * @Date: 2021/7/23
 */
@Service
@Slf4j
public class SpecificationImpl implements SpecificationService {

    @Autowired
    ProductRepository productRepository;
    @Autowired
    SpecificationRepository specificationRepository;
    @Autowired
    ProductPropertiesRepository productPropertiesRepository;

    @Override
    public void delById(Long productId, List<Long> specificationIds) {
        //查找商品信息
        Product product = productRepository.getProductOrThrow(productId);

        specificationRepository.delByIds(product.getId(), specificationIds);
    }

    @Override
    public void add(Long productId, List<Specification> specifications) {

        //查找商品信息
        Product product = productRepository.getProductOrThrow(productId);

        Map<String, Specification> specificationMap = findExitSpecs(product.getId());

        specifications.stream().forEach(specification -> {

            //校验是否存在
            String value = getValue(specification.getValue());
            if (specificationMap.containsKey(value)) {
                throw BussnessException.throwException("该规格已存在");
            }
            specification.setValue(value);
            log.info("specification {} 's value is {}", specification.getTage(), specification.getValue());
            specification.setProductId(product.getId());
        });

        specificationRepository.saveBatch(specifications);
    }

    @Override
    public void update(Long productId, Long specificationId, Specification specification) {
        //查找商品信息
        Product product = productRepository.getProductOrThrow(productId);

        Specification exit = specificationRepository.findByIdOrThrow(product.getId(), specificationId);

        String value = getValue(specification.getValue());
        if (StrUtil.isNotBlank(specification.getValue())
                && !exit.getValue().equals(value)) {
            //规格值不能重复
            Map<String, Specification> specificationMap = findExitSpecs(product.getId());

            if (specificationMap.containsKey(value)) {
                throw BussnessException.throwException("该规格已存在");
            }

        }
        //将规格id重大到小排列并组合为，分割字符串
        specification.setValue(value);
        BeanUtil.copyProperties(specification, exit);
        exit.setId(specificationId);
        //更新
        specificationRepository.updateById(exit);

    }

    @Override
    public SpecificationVO getOneById(Long productId, String properties) {
        //查找商品信息
        Product product = productRepository.getProductOrThrow(productId);
        String values = getValue(properties);


        Specification specification = specificationRepository.findByValueOrThrow(product.getId(), values);
        //查询属性详细信息，组合返回
        List<ProductProperties> productProperties = productPropertiesRepository.listByIds(Arrays.asList(specification.getValue().split(",")));
        return SpecificationAssembler.toVO(specification, productProperties);
    }

    @Override
    public IPage<SpecificationVO> getPage(PageSpecificationQuery query) {
        IPage<Specification> page = specificationRepository.getPage(query);

        List<Specification> specifications = page.getRecords();

        Set<Long> properIds = new HashSet<>();

        //获取所有商品属性id
        specifications.stream().forEach(s -> {
            log.info("specifications {} value is {}", s.getTage(), s.getValue());

            Set<Long> value = Arrays.asList(s.getValue().split(",")).stream()
                    .map(x -> Long.valueOf(x)).collect(Collectors.toSet());

            properIds.addAll(value);
        });
        log.info("properties ids are {}", properIds);

        //获取商品属性
        List<ProductProperties> properties = productPropertiesRepository.listByIds(properIds);
        //转为map用于查找
        Map<Long, ProductProperties> productPropertiesMap = properties.stream().collect(Collectors.toMap(ProductProperties::getId, p -> p));


        List<SpecificationVO> vos = new ArrayList<>();
        specifications.stream().forEach(specification -> {

            //获取商品属性
            List<ProductPropertiesVO> productProperties = new ArrayList<>();
            List<Long> thisSpecProIds = Arrays.asList(specification.getValue().split(",")).stream().map(x -> Long.valueOf(x)).collect(Collectors.toList());
            thisSpecProIds.stream().forEach(id -> {
                if (productPropertiesMap.containsKey(id)) {
                    ProductPropertiesVO productPropertiesVO = new ProductPropertiesVO();
                    ProductProperties p = productPropertiesMap.get(id);
                    BeanUtil.copyProperties(p, productPropertiesVO);
                    productProperties.add(productPropertiesVO);
                }
            });

            //vo转换
            SpecificationVO vo = new SpecificationVO();
            BeanUtil.copyProperties(specification, vo);
            vo.setProperties(productProperties);

            vos.add(vo);

        });

        IPage<SpecificationVO> voPage = new Page<>();
        BeanUtil.copyProperties(page, voPage);
        voPage.setRecords(vos);
        return voPage;
    }

    /**
     * 对属性id倒序排序并组合为字符串
     *
     * @param value
     * @return
     */
    private String getValue(String value) {

        List<String> ids = Arrays.asList(value.split(",")).stream()
                .sorted().collect(Collectors.toList());
        return ids.stream().collect(Collectors.joining(","));
    }

    private Map<String, Specification> findExitSpecs(Long productId) {
        //查找已存在的将规格id重大到小排列并组合为，分割字符串
        List<Specification> exitSpec = specificationRepository.listByProductId(productId);
        return exitSpec.stream().collect(Collectors.toMap(x -> x.getValue(), x -> x));
    }
}
